package com.lu.stack.gateway.filter.factory;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.InetAddress;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;

/**
 * @program rcs-alibaba
 * @description: 自定义全局的过滤器
 * @author: zhanglu
 * @create: 2021-05-18 15:23:00
 */
@Component
@Slf4j
public class ApiGatewayFilterFactory extends AbstractGatewayFilterFactory<ApiGatewayFilterFactory.Config> {

    public ApiGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
            String application = route.getId();
            Map<String, Object> metadata = route.getMetadata();
            ServerHttpRequest request = exchange.getRequest();
            InetAddress address = request.getRemoteAddress().getAddress();
            String realIp = address.getHostAddress();
            String servletPath = exchange.getRequest().getPath().toString();
            if (application.equals("lu-stack-api")) {
                //签名校验
                log.info("签名校验通过");

            }else {
                Map<String, Object> rs = new HashMap<>();
                rs.put("code", -1);
                rs.put("msg", "lu-test");
                return response(exchange, rs);
            }
            return chain.filter(exchange);
        });
    }


    public Mono<Void> response(ServerWebExchange exchange, Object obj){
        //签名校验
        DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(JSON.toJSONString(obj).getBytes(StandardCharsets.UTF_8));
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        //返回数据格式
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return exchange.getResponse().writeWith(Mono.just(wrap));
    }

    /**
     * 从Flux<DataBuffer>中获取字符串的方法
     *
     * @return 请求体
     */
    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();
        return resolveBodyFromRequest(body);
    }

    /**
     * 从Flux<DataBuffer>中获取字符串的方法
     *
     * @return 请求体
     */
    private String resolveBodyFromRequest(Flux<DataBuffer> body) {
        //获取请求体
        AtomicReference<String> bodyRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyRef.set(charBuffer.toString());
        });
        //获取request body
        return bodyRef.get();
    }

    public static class Config{
        private String name;
        private String prefixUrl;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPrefixUrl() {
            return prefixUrl;
        }

        public void setPrefixUrl(String prefixUrl) {
            this.prefixUrl = prefixUrl;
        }
    }

}
